<template>
  <div class="content-wrap link-ratio-wrap">
    <div class="content-box">
      <div class="content-left">
        <div class="top-wrap">
          <Card :bordered="false">
            <span slot="title">用气性质分类柱状图</span>
            <div class="chart-box">
              <h-bar3d :chartData="barlineData" :defaultOptions="hBar3dOptions" />
              <Spin fix size="large" v-if="barlineSpin">
                <Icon type="ios-loading" size="20" class="demo-spin-icon-load"></Icon>
                <div>图表生成中...</div>
              </Spin>
            </div>
          </Card>
        </div>
        <div class="bottom-wrap">
          <Card :bordered="false">
            <div slot="title">
              <span
                >表格 <span v-show="defaultDate">[ {{ showDate }} ]</span
                ><span v-show="currentMeterGasClass">[ {{ currentMeterGasClass }} ]</span></span
              >
              <span class="fr" title="操作表格数据" style="cursor: pointer;" @click="operateTable">
                <Icon type="md-qr-scanner" />
              </span>
            </div>
            <div class="table-box">
              <Table
                ref="table"
                class="table-item"
                :columns="tableColums"
                :loading="tableLoading"
                @on-row-click="tableClickHandle"
                :row-class-name="rowClassName"
                size="small"
                :height="tableHeight"
                :data="tableData"
              ></Table>
              <div class="page-box" v-show="tablePageData.total > 0">
                <Page
                  :total="tablePageData.total"
                  size="small"
                  simple
                  @on-change="changeTablePageHandle"
                  :page-size="tablaPageParams.pageSize"
                />
              </div>
            </div>
          </Card>
        </div>
      </div>
      <div class="content-center">
        <div class="chart-box">
          <Card :bordered="false">
            <div slot="title" class="clearfix">
              <span class="fl card-tit"
                >用气量环比下降分布图<span v-show="defaultDate">[ {{ showDate }} ]</span></span
              >
              <div class="tc">
                <Dropdown trigger="custom" :visible="paramsFlag" class="params-setting-box">
                  <Button type="primary" @click="handleParams(true)" size="small">参数设置</Button>
                  <DropdownMenu slot="list">
                    <Form ref="paramsForm" :label-width="90" :model="paramsForm" :rules="pramsValidate">
                      <FormItem label="用气范围" prop="gasRange">
                        <Select placeholder="请选择范围" v-model="paramsForm.gasRange">
                          <Option v-for="item in usegasRange" :key="item.value" :value="item.value">{{
                            item.name
                          }}</Option>
                        </Select>
                      </FormItem>
                      <FormItem prop="rangeNum" label="自定义范围">
                        <div class="self-range">
                          <InputNumber v-model="paramsForm.startNum" placeholder="起始" />
                          <span class="space-line"></span>
                          <InputNumber v-model="paramsForm.endNum" placeholder="截至" />
                        </div>
                      </FormItem>
                      <FormItem label="点半径" prop="pointRadius">
                        <Slider :min="1" :max="10" v-model="paramsForm.pointRadius" style="width:100%"></Slider>
                      </FormItem>
                      <div class="bottom-box tr">
                        <Button type="primary" @click="handleParamsSubmit('paramsForm')" size="small">确定</Button>
                        <Button type="default" @click="handleParams(false)" size="small" style="margin-left:10px"
                          >关闭</Button
                        >
                      </div>
                    </Form>
                  </DropdownMenu>
                </Dropdown>
                <Button type="info" size="small" @click="refreshPage" style="margin-left:10px"
                  ><Icon type="md-refresh" />刷新</Button
                >
              </div>
            </div>
            <div class="chart-box">
              <effect-scatter-map
                id="linkRatioWeekScatterMap"
                :fetchData="fetchMapAndZidanData"
                :mapData="locationScatterMapData"
                :centerPoint="markPoint"
                :rangeParams="effectScatterMapPointRangeParams"
                defaultColor="#2b0ff6"
                :options="locationScatterMapOptions"
                @pointClick="escattermapPointClickHandle"
                @pointDblclick="escattermapPointDblclickHandle"
              />
            </div>
          </Card>
        </div>
      </div>
      <div class="content-right">
        <div class="top-box">
          <Card :bordered="false">
            <div slot="title" class="clearfix">
              <span class="fl card-tit">用气量环比子弹图</span>
              <div class="fr">
                <DatePickerWeek
                  size="small"
                  :defaultDate="zidanfilterDate"
                  @on-change="changeZidanDateHandle"
                  :options="zidanDisabledDate"
                  style="width:140px"
                />
              </div>
            </div>
            <div class="zidan-box">
              <div class="zidan-item" v-for="(item, index) of zidanList" :key="index">
                <h-bullet :id="'zidan' + index" :chartData="item" :defaultOptions="hBulletOptions" />
              </div>
            </div>
            <Spin fix size="large" v-if="rightShowSpin">
              <Icon type="ios-loading" size="20" class="demo-spin-icon-load"></Icon>
              <div>图表生成中...</div>
            </Spin>
          </Card>
        </div>
        <div class="bottom-box">
          <Card :bordered="false">
            <div slot="title">
              详情
            </div>
            <div class="detail-box">
              <meter-detail
                :currentMeterId="currentMeterId"
                :content="meterDetail"
                :columnNames="meterDetailColumns"
                :currentDate="currentDate"
              />
            </div>
          </Card>
        </div>
      </div>
      <!-- 表格操作 -->
      <Modal
        class="operate-table"
        fullscreen
        v-model="showOperateTableFlag"
        :title="showDate"
        @on-cancel="operateTableCancel"
      >
        <div
          :is="operateTableTemplate"
          :params="{
            currentDate: operateDate,
            gasClass: currentMeterGasClass,
            meterIds: currentMeterIds,
            meterId: dblClickMeterId,
            type: tplType
          }"
        ></div>
        <div slot="footer">
          <Button @click="operateTableCancel" ghost>关闭</Button>
        </div>
      </Modal>
    </div>
  </div>
</template>
<script>
import dayjs from 'dayjs'
import weekOfYear from 'dayjs/plugin/weekOfYear'
import { each, isEmpty, filter, isNull, split, toString, merge } from 'lodash'
import { barline, heatmapBmapChartData, tableData, meterDetail } from '@/api/linkRatioWeek'
import setTableHeightMixin from '@/mixins/setTableHeight'
import DatePickerWeek from '@/commons/DatePickerWeek'
import { hBulletOptions, hBar3dOptions, locationScatterMapOptions } from './chartOptions/index'
import tableColums from './tableColums'
import meterDetailColumns from './meterDetailColumns'

dayjs.extend(weekOfYear)

const usegasRange = Object.freeze([
  {
    name: '小于10方',
    value: '0-10'
  },
  {
    name: '10-100方',
    value: '10-100'
  },
  {
    name: '100-1000方',
    value: '1000-1000'
  },
  {
    name: '1000-10000方',
    value: '1000-10000'
  },
  {
    name: '大于10000方',
    value: '10000-infinite'
  }
])

export default {
  name: 'linkRatioWeek',
  mixins: [setTableHeightMixin],
  components: {
    DatePickerWeek,
    MeterDetail: () => import('@/commons/MeterDetail'),
    HBar3d: () => import('@/commons/charts/HBar3d'),
    HBullet: () => import('@/commons/charts/HBullet'),
    EffectScatterMap: () => import('@/commons/charts/EffectScatterMap'),
    OperateTable: () => import('./components/OperateTable')
  },
  data() {
    /**
     * desc: 自定义范围数据验证
     * param {type}
     * return:
     */
    const validateRangeNum = (rule, value, callback) => {
      const { startNum = 0, endNum = 0 } = this.paramsForm
      if ((parseInt(endNum) || parseInt(startNum)) && parseInt(startNum) >= parseInt(endNum)) {
        return callback(new Error('起始值不能大于结束值'))
      }
      callback()
    }
    return {
      tplType: 'week',
      tableLoading: false,
      tableData: [],
      tablaPageParams: {
        pageNum: 1,
        pageSize: 20,
        order: 'asc'
      },
      tablePageData: {
        total: 0
      },
      currentFilterDate: null,
      locationScatterMapData: null,
      markPoint: null,
      zidanList: [],
      zidanfilterDate: undefined,
      rightShowSpin: false,
      currentZidanAndTableDay: null,
      defaultPointRadius: 8,
      currentMeterId: undefined,
      dblClickMeterId: undefined,
      showOperateTableFlag: false,
      operateTableTemplate: null,
      showOnceMonthEndDate: undefined,
      currentZidanAndMapData: null,
      paramsFlag: false,
      paramsForm: {
        gasRange: '1000-10000',
        startNum: 0,
        endNum: 0,
        pointRadius: 3
      },
      pramsValidate: {
        rangeNum: { validator: validateRangeNum, trigger: 'blur' }
      },
      effectScatterMapPointRangeParams: null,
      barlineData: null,
      barlineSpin: false,
      currentMeterGasClass: null,
      hasMoveFlag: false,
      currentMeterIds: null,
      meterDetail: {},
      showDate: null,
      operateDate: null
    }
  },
  computed: {
    defaultDate() {
      return this.$config.nowDate
    },
    zidanDisabledDate() {
      const _this = this
      return {
        disabledDate(date) {
          return date && date.valueOf() > dayjs(_this.defaultDate).valueOf()
        }
      }
    },
    locationScatterMapOptions() {
      return locationScatterMapOptions
    },
    tableColums() {
      return tableColums
    },
    currentModalMonth() {
      return `当前时间: ${dayjs(this.defaultDate).format('YYYY-MM')}`
    },
    usegasRange() {
      return usegasRange
    },
    hBar3dOptions() {
      return hBar3dOptions
    },
    hBulletOptions() {
      return hBulletOptions
    },
    meterDetailColumns() {
      return meterDetailColumns
    },
    currentDate() {
      return this.currentZidanAndTableDay
        ? dayjs(this.currentZidanAndTableDay).format('YYYY-MM')
        : this.defaultDate && dayjs(this.defaultDate).format('YYYY-MM')
    }
  },
  created() {
    // 表格和热力图时间展示
    const _sYear = dayjs(this.defaultDate).year()
    const _sWeek = dayjs(this.defaultDate).subtract(1, 'week').week()
    this.showDate = `${_sYear}年第${_sWeek}周`
    this.operateDate = `${_sYear}-${_sWeek}`

    const _rDate = dayjs(this.defaultDate).subtract(2, 'week')
    this.zidanfilterDate = dayjs(_rDate).format('YYYY-MM-DD')
    const _year = dayjs(_rDate).year()
    const _week = dayjs(_rDate).week()
    this.currentFilterDate = `${_year}-${_week}`
  },
  methods: {
    operateTableCancel() {
      this.showOperateTableFlag = false
      this.operateTableTemplate = null
    },
    /**
     * @msg: 表格中数据异常列突出显示
     * @param {type}
     * @return:
     */
    rowClassName(row = {}) {
      const { status } = row
      if (Number(status) === 1) {
        return 'row-abnormal'
      }
      return ''
    },
    /**
     * @msg: 表格点击
     * @param {type}
     * @return:
     */
    tableClickHandle(row = {}) {
      const { meterId } = row
      if (toString(this.currentMeterId) !== toString(meterId)) {
        this.currentMeterId = meterId
        this.modifyCoordinateData(row)
        this.fetchMeterDetail(meterId)
      }
    },
    changeStartTime(type, flag) {
      this[type] = {
        ...this[type],
        [flag]: null
      }
    },
    /**
     * @msg: 子弹图日期修改
     * @param {type}
     * @return:
     */
    changeZidanDateHandle(date) {
      this.currentFilterDate = date
      this.operateDate = date
      this.fetchMapAndZidanData()
    },
    /**
     * @msg: 整理中间区域大地图数据
     * @param {data}
     * @return:
     */
    modifyEffectScatterMapData(data = {}) {
      const mapData = []
      const { meterList = [] } = data
      each(meterList, item => {
        // eslint-disable-next-line no-unused-vars
        const { usageAll, meterId, latitude, value, longitude } = item
        mapData.push({
          name: meterId,
          value: [longitude, latitude, value]
        })
      })
      this.locationScatterMapData = mapData
    },
    /**
     * @msg: 整理子弹图数据并形成列表，同时默认第一条数据为地图展示数据
     * @param {type}
     * @return:
     */
    modifyMapAndZidanData(data = []) {
      const _retList = []
      const _this = this
      each(data, item => {
        // count: 实际值  targer: 目标值
        const { name, count, target } = item
        const _cateList = []
        const _serList = []
        _cateList.push(name)
        _serList.push({
          y: count,
          target
        })

        _retList.push(
          merge({}, hBulletOptions, {
            plotOptions: {
              series: {
                cursor: 'pointer',
                events: {
                  click: function(e) {
                    _this.zidanSeriesClickHandle(e, this)
                  }
                }
              }
            },
            xAxis: {
              categories: _cateList
            },
            series: [
              {
                data: _serList
              }
            ]
          })
        )
      })
      this.zidanList = _retList

      // 子弹图和地图数据一起返回，默认展现第一条数据中 meterList 为地图数据
      this.modifyEffectScatterMapData(data[0])
    },
    /**
     * description: 右侧子弹图和中间地图数据请求
     * param {}
     * return: void
     */
    fetchMapAndZidanData() {
      // 初始化参数设置
      const { pointRadius, gasRange } = this.paramsForm
      if (gasRange) {
        const rangeList = split(gasRange, '-')
        this.effectScatterMapPointRangeParams = {
          min: rangeList[0],
          max: rangeList[1],
          pointRadius
        }
      }

      const toDay = this.currentFilterDate
      heatmapBmapChartData({
        toDay,
        type: this.tplType
      })
        .then(res => {
          this.$Loading.finish()
          if (res.date) {
            // 缓存子弹图和地图数据，用于点击对应子弹图展示其对应的地图数据，地图数据保存在每条数据的 meterList 里面
            this.currentZidanAndMapData = res.date
            this.modifyMapAndZidanData(res.date)
            // 首次加载子弹图获取数据成功，然后默认选择第一条数据中 meterIds，请求表格数据
            const { meterIds = undefined } = res.date[0]
            this.currentMeterIds = meterIds
            this.fetchTableData({
              meterIds
            })
            this.fetchBarlineData({
              meterIds
            })
          }
        })
        .catch(() => {
          this.$Loading.finish()
        })
    },
    /**
     * @msg: 子弹图选中，筛选出对应的地图数据并展现, meterList 为地图数据
     * @param {type}
     * @return:
     */
    zidanSeriesClickHandle(data) {
      this.currentMeterId = null
      this.meterDetail = null
      this.markPoint = null
      this.currentMeterGasClass = null
      const {
        point: { category }
      } = data
      const currentList = filter(this.currentZidanAndMapData, item => item.name === category)
      // 渲染地图
      this.modifyEffectScatterMapData(currentList[0])
      // 清除表格选中数据
      this.currentMeterId = undefined
      const { meterIds } = currentList[0]
      this.currentMeterIds = meterIds
      this.fetchTableData({
        meterIds
      })
      this.fetchBarlineData({
        meterIds
      })
    },
    /**
     * @msg: 这里表格数据
     * @param {type}
     * @return:
     */
    modifyTabelData(data = {}) {
      const { list = [], total, pageNum, pageSize } = data
      this.tableData = list
      this.tablePageData = {
        ...this.tablePageData,
        total,
        pageNum,
        pageSize
      }
      this.$nextTick(() => {
        this.setTableHeight()
      })
    },
    /**
     * description: 获取左侧表格数据
     * param {params} 参数
     * return: void
     */
    fetchTableData(params = {}) {
      this.tableLoading = true
      tableData({
        ...this.tablaPageParams,
        ...params,
        type: this.tplType
      })
        .then(res => {
          this.$Loading.finish()
          this.tableLoading = false
          if (res.date) {
            this.modifyTabelData(res.date)
          }
        })
        .catch(() => {
          this.$Loading.finish()
          this.tableLoading = false
        })
    },
    /**
     * @msg: 表格页面修改
     * @param {type}
     * @return:
     */
    changeTablePageHandle(data) {
      this.tablaPageParams = {
        ...this.tablaPageParams,
        pageNum: data
      }
      this.$nextTick(() => {
        this.fetchTableData({
          meterIds: this.currentMeterIds
        })
      })
    },
    /**
     * 整理
     * @return {[type]} [description]
     */
    modifyCoordinateData(data) {
      const mapData = []
      const { meterId, latitude, longitude } = data
      mapData.push({
        name: meterId,
        value: [longitude, latitude, this.defaultPointRadius]
      })
      this.currentMeterId = meterId + ''
      this.markPoint = [longitude, latitude]
    },
    /**
     * @msg: 表格数据操作
     * @param {type}
     * @return:
     */
    operateTable() {
      if (isEmpty(this.tableData)) {
        this.$Notice.warning({
          title: '操作提示',
          desc: '数据正在准备中，请稍后再操作'
        })
      } else {
        // 点击表格操作清空选中数据
        this.dblClickMeterId = undefined
        this.showOperateTableFlag = true
        this.operateTableTemplate = 'OperateTable'
      }
    },
    /**
     * @msg: 刷新页面
     * @param {type}
     * @return:
     */
    refreshPage() {
      this.fetchMapAndZidanData()
    },
    /**
     * description: 参数操作框显示、隐藏
     * param {type}
     * return:
     */
    handleParams(status) {
      this.paramsFlag = status
    },
    /**
     * description: 参数修改保存
     * param {type}
     * return:
     */
    handleParamsSubmit(form) {
      this.$refs[form].validate(valid => {
        if (valid) {
          const { endNum, startNum, pointRadius, gasRange } = this.paramsForm
          let min = 0
          let max = 0
          if (isNull(endNum) || isNull(startNum) || (!startNum && !endNum)) {
            const rangeList = split(gasRange, '-')
            min = rangeList[0]
            max = rangeList[1]
          } else {
            // 自定义范围
            min = startNum
            max = endNum
          }
          if (min && max) {
            this.effectScatterMapPointRangeParams = {
              min,
              max,
              pointRadius
            }
            this.paramsFlag = false
          } else {
            this.$Notice.warning({
              title: '操作提示',
              desc: '请确定用气范围后再操作'
            })
          }
        }
      })
    },
    /**
     * @msg: 柱状图数据处理
     * @param {type}
     * @return:
     */
    modifyBarlineData(data) {
      const _this = this
      const _cateList = []
      const _serList = []

      each(data, item => {
        const { meterGasClass, count } = item
        _cateList.push(meterGasClass)
        _serList.push({
          meterGasClass,
          y: count
        })
      })
      this.barlineData = merge({}, hBar3dOptions, {
        plotOptions: {
          series: {
            cursor: 'pointer',
            events: {
              click: function(e) {
                _this.barLineClickHandle(e, this)
              }
            }
          }
        },
        xAxis: {
          categories: _cateList
        },
        series: [
          {
            data: _serList
          }
        ]
      })
    },
    /**
     * description: 柱状图请求
     * param {type}
     * return:
     */
    fetchBarlineData(params) {
      this.barlineSpin = true
      barline({
        ...params,
        type: this.tplType
      }).then(res => {
        this.barlineSpin = false
        if (res.date) {
          this.modifyBarlineData(res.date)
        }
      })
    },
    /**
     * desc: 柱状图点击,更新表格数据
     * param {data} 点击柱子对应参数
     * return: void
     */
    barLineClickHandle(data) {
      this.markPoint = null
      this.currentMeterId = null
      const {
        point: { meterGasClass }
      } = data
      this.currentMeterGasClass = meterGasClass
      this.fetchTableData({
        meterGasClass,
        meterIds: this.currentMeterIds
      })
    },
    /**
     * desc: 中间区域地图覆盖物点击
     * param {type}
     * return: void
     */
    escattermapPointClickHandle(params = {}) {
      const {
        data: { name }
      } = params
      if (toString(this.currentMeterId) !== toString(name)) {
        this.currentMeterId = name
        this.fetchMeterDetail(name)
      }
    },
    /**
     * desc: 中间区域地图覆盖物双击
     * param {type}
     * return:
     */
    escattermapPointDblclickHandle(params = {}) {
      this.escattermapPointClickHandle(params) // 双击情况下实现单击相同效果
      const {
        data: { name }
      } = params
      this.dblClickMeterId = name
      this.showOperateTableFlag = true
      this.operateTableTemplate = 'OperateTable'
    },
    /**
     * @desc: 获取表具详情
     * @param {type}
     * @return:
     */
    fetchMeterDetail(meterId) {
      meterDetail(meterId).then(res => {
        if (res.date) {
          this.meterDetail = res.date
        } else {
          this.meterDetail = null
        }
      })
    }
  }
}
</script>
<style lang="less" scoped>
@import './index.less';
</style>
